package com.alibaba.citrus.ots.platform.enhance.facade.service.log;

import com.alibaba.acm.shaded.com.google.common.collect.Lists;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.log.ModuleEnum;
import com.alibaba.citrus.ots.common.log.OperateTypeEnum;
import com.alibaba.citrus.ots.platform.enhance.repository.OperateLogQueryRepository;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.model.dto.BaselineGetEmployeeByIdsAllRequest;
import com.epoch.app.bcots.model.dto.EmployeeSDO;
import com.epoch.app.bcots.service.BaseDataService;
import com.epoch.app.otsplatformenhance.domain.operatelog.model.OperateLog;
import com.epoch.app.otsplatformenhance.domain.operatelog.service.OperateLogService;
import com.epoch.app.otsplatformenhance.model.dto.*;
import com.epoch.app.otsplatformenhance.queryoperatelog.dto.PageQueryOperateLogRequest;
import com.epoch.app.otsplatformenhance.queryoperatelog.service.QueryOperateLogService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: qiaojiange
 * @create: 2021/11/09
 * @Description 查询操作日志
 */
@Component
@Primary
public class QueryOperateLogServiceImpl implements QueryOperateLogService {

    private static final Log log = Log.getLogger(QueryOperateLogServiceImpl.class);

    @Resource
    private OperateLogQueryRepository operateLogQueryRepository;

    @Resource
    private OperateLogService operateLogService;

    @Resource
    private BaseDataService baseDataService;

    @Override
    @FacadeInvoker
    public Result<List<OperateLog>> queryOperateLog(OperateQueryInfoRequest operateQueryInfoRequest) {
        Result<List<OperateLog>> operateLogList = operateLogQueryRepository.queryOperateLog(operateQueryInfoRequest);
        return operateLogList;
    }

    @Override
    public Result<List<OperateLogDiff>> queryOperateLogRowDiff(OperateQueryInfoRequest operateQueryInfoRequest) {
        Result<List<OperateLog>> listResult = queryOperateLog(operateQueryInfoRequest);
        if (CollectionUtils.isEmpty(listResult.getResult())) {
            return Result.success(new ArrayList<>());
        }

        return Result.success(listResult.getResult().stream().map(item -> {
            OperateLogDiff operateLogDiff = new OperateLogDiff();
            String diff = item.getDiff();
            BeanUtils.copyProperties(item, operateLogDiff);
            //解析逻辑
            if (StringUtils.isNotBlank(diff)) {
                List<RowDiff> parseResult = obtainOperateLogDiff(diff);
                operateLogDiff.setRowDiff(parseResult);
            }
            return operateLogDiff;
        }).collect(Collectors.toList()));

    }

    /**
     * 解析差异信息
     *
     * @param diff
     * @return
     */
    private List<RowDiff> obtainOperateLogDiff(String diff) {

        List<RowDiff> rowDiffs = JSON.parseArray(diff, RowDiff.class);
        rowDiffs.forEach(row -> {
            String newLine = row.getNewLine();
            if (StringUtils.isNotBlank(newLine)) {
                String[] newLineVar = newLine.replace("\\", "").split(":");
                if (row.getTag().equals("INSERT") || row.getTag().equals("CHANGE")) {
                    if (newLineVar.length > 1) {
                        row.setFieldName(newLineVar[0].replace("\"","").trim());
                    }
                }
                if (newLineVar.length > 1 && Objects.nonNull(newLineVar[1])) {
                    row.setNewValue(newLineVar[1].substring(0, newLineVar[1].length() - 1).replace("\"",""));
                }


            }

            String oldLine = row.getOldLine();
            if (StringUtils.isNotBlank(oldLine)) {
                String[] oldLineStrs = oldLine.replace("\\", "").split(":");
                if (row.getTag().equals("DELETE")) {
                    row.setFieldName(oldLineStrs[0].replace("\"","").trim());
                }
                if (oldLineStrs.length > 1 && Objects.nonNull(oldLineStrs[1])) {
                    row.setOldValue(oldLineStrs[1].substring(0, oldLineStrs[1].length() - 1).replace("\"",""));
                }
            }
        });

        return rowDiffs;

    }

    @Override
    @FacadeInvoker
    public Result<List<OperateLogResponse>> pageQueryOperateLog(PageQueryOperateLogRequest pageQueryOperateLogRequest) {
        List<OperateLogResponse> responses = Lists.newArrayList();
        OperateLogLoadListRequest operateQueryInfoRequest = convertRequest(pageQueryOperateLogRequest);
        log.info("QueryOperateLogService.pageQueryOperateLog.operateQueryInfoRequest={}", JSONObject.toJSONString(operateQueryInfoRequest));
        Result<List<OperateLog>> listResult = operateLogService.queryOperateLogByPage(operateQueryInfoRequest);
        log.info("QueryOperateLogService.pageQueryOperateLog.listResult={}", JSONObject.toJSONString(listResult));
        if (!listResult.isSuccess()) {
            return Result.fail("OTS-12-002-01-10-001", ErrorMessage.code("OTS-12-002-01-10-001", null).getDisplayErrorMessage());
        }
        List<OperateLog> list = listResult.getResult();
        if (CollectionUtils.isEmpty(list)) {
            return Result.listSuccess(responses, responses.size());
        }
        //名称转换
        Map<String, String> employeeMap = new HashMap<>();
        List<String> idList = list.stream().filter(log -> StringUtils.isNotEmpty(log.getOperatorId()))
                .map(log -> log.getOperatorId().replace("CZ_", "").trim())
                .distinct().collect(Collectors.toList());
        log.info("QueryOperateLogService.pageQueryOperateLog.idList={}", JSONObject.toJSONString(idList));
        Result<List<EmployeeSDO>> employeeResult = baseDataService.baselineGetEmployeeByIdsAll(BaselineGetEmployeeByIdsAllRequest.builder().ids(idList).build());
        log.info("QueryOperateLogService.pageQueryOperateLog.employeeResult={}", JSONObject.toJSONString(employeeResult));
        if (employeeResult.isSuccess() && CollectionUtils.isNotEmpty(employeeResult.getResult())) {
            employeeMap = employeeResult.getResult().stream().collect(Collectors.toMap(EmployeeSDO::getId, EmployeeSDO::getName));
        }
        Map<String, String> moduleEnumMap = ModuleEnum.getMap();
        Map<Integer, String> operateTypeEnumMap = OperateTypeEnum.getMap();
        for (OperateLog operateLog : list) {
            OperateLogResponse operateLogResponse = convertResponse(employeeMap, moduleEnumMap, operateTypeEnumMap, operateLog);
            responses.add(operateLogResponse);
        }
        log.info("QueryOperateLogService.pageQueryOperateLog.responses={}", JSONObject.toJSONString(responses));
        return Result.listSuccess(responses, listResult.getTotal());
    }

    private OperateLogResponse convertResponse(Map<String, String> employeeMap, Map<String, String> moduleEnumMap, Map<Integer, String> operateTypeEnumMap, OperateLog operateLog) {
        OperateLogResponse operateLogResponse = new OperateLogResponse();
        operateLogResponse.setId(operateLog.getId());
        operateLogResponse.setTraceId(operateLog.getTraceId());
        if (null != operateLog.getOperateType()) {
            operateLogResponse.setOperateType(operateLog.getOperateType());
            if (operateTypeEnumMap.containsKey(operateLog.getOperateType())) {
                operateLogResponse.setOperateTypeText(operateTypeEnumMap.get(operateLog.getOperateType()));
            }
        }
        if (StringUtils.isNotEmpty(operateLog.getModuleId())) {
            operateLogResponse.setModuleId(operateLog.getModuleId());
            if (moduleEnumMap.containsKey(operateLog.getModuleId())) {
                operateLogResponse.setModuleName(moduleEnumMap.get(operateLog.getModuleId()));
            }
        }
        if (StringUtils.isNotEmpty(operateLog.getOperatorId())) {
            operateLogResponse.setOperatorId(operateLog.getOperatorId());
            if (employeeMap.containsKey(operateLog.getOperatorId().replace("CZ_", "").trim())) {
                operateLogResponse.setOperatorName(employeeMap.get(operateLog.getOperatorId().replace("CZ_", "").trim()));
            }
        }
        operateLogResponse.setGmtCreate(operateLog.getGmt_create());
        return operateLogResponse;
    }

    private OperateLogLoadListRequest convertRequest(PageQueryOperateLogRequest pageQueryOperateLogRequest) {
        OperateLogLoadListRequest operateQueryInfoRequest = new OperateLogLoadListRequest();
        if (StringUtils.isNotEmpty(pageQueryOperateLogRequest.getTraceId())) {
            operateQueryInfoRequest.setTraceId(pageQueryOperateLogRequest.getTraceId());
        }
        if (null != pageQueryOperateLogRequest.getOperateType()) {
            operateQueryInfoRequest.setOperateType(pageQueryOperateLogRequest.getOperateType());
        }
        if (StringUtils.isNotEmpty(pageQueryOperateLogRequest.getModuleId())) {
            operateQueryInfoRequest.setModuleId(pageQueryOperateLogRequest.getModuleId());
        }
        if (null != pageQueryOperateLogRequest.getOperatorId()) {
            operateQueryInfoRequest.setOperatorId("CZ_" + pageQueryOperateLogRequest.getOperatorId());
        }
        operateQueryInfoRequest.setStart(pageQueryOperateLogRequest.getStart());
        operateQueryInfoRequest.setLimit(pageQueryOperateLogRequest.getLimit());
        operateQueryInfoRequest.setDir(pageQueryOperateLogRequest.getDir());
        operateQueryInfoRequest.setAsc(false);
        return operateQueryInfoRequest;
    }

    @Override
    @FacadeInvoker
    public Result<List<KeyValueModel>> getModuleDropDown() {
        List<KeyValueModel> list = Lists.newArrayList();
        for (ModuleEnum value : ModuleEnum.values()) {
            KeyValueModel keyValueModel = new KeyValueModel();
            keyValueModel.setLabel(value.getModuleName());
            keyValueModel.setValue(value.getModuleId());
            list.add(keyValueModel);
        }
        return Result.listSuccess(list, list.size());
    }

    @Override
    @FacadeInvoker
    public Result<List<KeyValueModel>> getOperateTypeDropDown() {
        List<KeyValueModel> list = Lists.newArrayList();
        for (OperateTypeEnum value : OperateTypeEnum.values()) {
            KeyValueModel keyValueModel = new KeyValueModel();
            keyValueModel.setLabel(value.getDesc());
            keyValueModel.setValue(value.getOperateType().toString());
            list.add(keyValueModel);
        }
        return Result.listSuccess(list, list.size());
    }
}
